#pragma once

#include <glibmm.h>
#include <vector>

// tmp hack...
#include "../Shared/GObjHelpers.hpp"

namespace EGlib
{
  class ProcessRunner;
  
  class IProcessInputProvider;
  class IProcessOutputHandler;
  
  class Process : public BuildNG::Object
  {
    friend class ProcessRunner;

  public:
    Process(const Glib::ustring &executable_name);

    static Glib::RefPtr<Process> create(const Glib::ustring &executable_name);

    void set_working_directory(const Glib::ustring &working_dir);
    void set_arguments(const Glib::ArrayHandle<Glib::ustring> &args);
    void add_argument(const Glib::ustring &arg);
    void add_arguments(const Glib::ArrayHandle<std::string> &args);

    /// Adds arguments from the given string.
    /// The string is parsed into a set of command line options, 
    /// in the way provided by the \ref parse_method argument
    enum ArgumentParseMethod
    {
      ArgumentParseMethod_Bash,
      ArgumentParseMethod_Windows,
      ArgumentParseMethod_Native,
    };
    void add_arguments_string(const Glib::ustring &args,ArgumentParseMethod parse_method);

    void add_env(const Glib::ustring &var_name,const Glib::ustring &val);
    void set_inherit_env(bool inherit_env);

    void set_stdin_channel(Glib::RefPtr<Glib::IOChannel> stdin_channel);
    void set_stdout_channel(Glib::RefPtr<Glib::IOChannel> stdout_channel);
    void set_stderr_channel(Glib::RefPtr<Glib::IOChannel> stderr_channel);
    
    void set_stdin_provider(Glib::RefPtr<IProcessInputProvider> stdin_provider);
    void set_stdout_handler(Glib::RefPtr<IProcessOutputHandler> stdout_handler);
    void set_stderr_handler(Glib::RefPtr<IProcessOutputHandler> stderr_handler);
    
    int spawn_sync();

  private:
    Glib::ustring               executable_name;
    Glib::ustring               working_dir;
    std::vector<Glib::ustring>  args;
    std::map<Glib::ustring,Glib::ustring>  env_vars;
    bool                        inherit_env;

    Glib::RefPtr<IProcessInputProvider>     stdin_provider;
    Glib::RefPtr<IProcessOutputHandler>     stdout_handler;
    Glib::RefPtr<IProcessOutputHandler>     stderr_handler;
  };
  
  class IProcessInputProvider : public BuildNG::Interface
  {
  public:
    virtual void provide_input(char *buffer,int max_size,int &actual_size_provided) = 0;
  };
  
  class IProcessOutputHandler : public BuildNG::Interface
  {
  public:
    virtual void handle_output(char *buffer,int buffer_size) = 0;
  };
}

